home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / vsuck / VSuckExamples.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  13.7 KB  |  481 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. /*
  7. **      $Id: VSuckExamples.c,v 30.0 1994/06/10 18:09:36 dice Exp $
  8. **
  9. **      Hack of early VSuck to extract examples for testing.
  10. **
  11. **      (C) Copyright 1992, Obvious Implementations, All Rights Reserved
  12. */
  13. #define D(x)    ;
  14. #define D1(x)   ;
  15. #define D2(x)   ;
  16. #define LINE_WIDTH      77      // So text won't wrap on 640 pixel wide screens
  17. #define MAX_PARAGRAPH   8000    // Yes... build that same limitation in.
  18.  
  19. #define MIN_INDENT      4
  20. #define BODY_INDENT     8
  21. #define OPTION_INDENT   12
  22. #define EXAMPLE_INDENT  4       // Extra bytes past normal indent
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27.  
  28. #define unless(x)       if(!(x))
  29. #define CR              13
  30. #define LF              10
  31. #define FF              12
  32. #define TAB             9
  33.  
  34. /*******************************************************************************
  35. **      Globals
  36. */
  37. FILE    *outfile;                       // FP for final output
  38.  
  39. char    allspaces[] ="                                                                                ";
  40. char    allhash[]   ="################################################################################";
  41. char    filename[]  ="**INVALID***********************************************************************";
  42. char    filename_nopath[]  ="**INVALID*************************";
  43. char    *pathname;
  44. char    *examplename=0;
  45. char    outbuf[LINE_WIDTH+3];           // Leave room for CR,LF,NULL
  46. char    formatbuf[MAX_PARAGRAPH];       // Yes... build the same limitation in.
  47. char    indenttext[LINE_WIDTH+3];       // For text in the left margin
  48. char    indenttextvalid=0;              //      -option  This is an option
  49.  
  50. int     bodyindent      =BODY_INDENT;
  51. int     optionindent    =OPTION_INDENT;
  52. int     indent          =0;
  53.  
  54. char          *startinp;                // Start of input
  55. register char *inp;                     // Walking input pointer
  56.  
  57. int     enum_val=0;                     // For @ENUM auto-counting
  58.  
  59.  
  60.  
  61. /*******************************************************************************
  62. **      Prototypes
  63. */
  64. FilterCR(register char *leading);
  65. void ProcessFile();
  66. void putn(char *string,char terminator);
  67. void FormatParagraph(int slen,char *prestring);
  68. int  CollectParagraph(void);
  69.  
  70.  
  71. /******************************************************************************/
  72. main(int argc,char *argv[])
  73. {
  74. FILE    *infile;
  75. long     insize;
  76.  
  77.     if (argc < 3 || ( argc == 2  &&  *argv[1]=='?' ) ) {
  78.         printf("VSuckExamples <infile> <outdir> [example_name]\n");
  79.         printf("; Extract examples from Ventura.  Use for compile-checking.\n");
  80.         exit(5);
  81.         }
  82.  
  83.     D2(printf("Argc=%d, Arg1=%s, Arg2=%s\n",argc,argv[1],argv[2]));
  84.  
  85.     unless( infile=fopen(argv[1],"r" ) ) {
  86.         printf("Error: Can't read \"%s\"\n",argv[1]);
  87.         exit(10);
  88.         }
  89.     outfile=0;
  90.     pathname=argv[2];
  91.  
  92.     if( argc == 4 ) {
  93.         examplename=argv[3];
  94.         printf("Extracting only example %s\n", examplename);
  95.         }
  96.  
  97.     /*
  98.     unless( outfile=fopen(argv[2],"w" ) ) {
  99.         printf("Error: Can't write to \"%s\"\n",argv[2]);
  100.         fclose(infile);
  101.         exit(10);
  102.         }
  103.      */
  104.  
  105.     inp=0;
  106.     fseek(infile,0,2);
  107.     if( insize=ftell(infile) )
  108.         {
  109.         fseek(infile,0,0);
  110.         if ( inp=malloc( insize+4 ) )
  111.             {
  112.             if ( insize==fread( inp,1,insize,infile ) )
  113.                 {
  114.                 inp[insize]  =0;        // Lots of space for sloppy code
  115.                 inp[insize+1]=0;        // to read past without harm
  116.                 inp[insize+2]=0;
  117.                 inp[insize+3]=0;
  118.                 }
  119.                 else
  120.                 {
  121.                 printf("Error: Can't read \"%s\"\n",argv[1]);
  122.                 free( inp );
  123.                 inp=0;
  124.                 }
  125.             }
  126.             else
  127.             {
  128.             printf("Error: Out of memory (%ld bytes required)\n",insize+2);
  129.             }
  130.         }
  131.  
  132.     startinp=inp;
  133.     if( inp ) {
  134.         FilterCR(inp);          // Nuke all CR's
  135.         ProcessFile();
  136.         free( startinp );
  137.         }
  138.  
  139.     fclose( infile );
  140.     if (outfile)
  141.         fclose( outfile );
  142.     printf("Exiting.  Have a _very_ nice day.\n");
  143. }
  144.  
  145.  
  146. /*******************************************************************************
  147. **      Misc utility functions
  148. */
  149. //      Like puts, put terminates at given character
  150. void putn(char *string,char terminator)
  151. {
  152. char *temp;
  153.  
  154.         temp=strchr(string,terminator);
  155.         if (temp)
  156.             fwrite(string,temp-string+1,1,stdout);
  157. }
  158.  
  159. //      Like strnlen, but counts to given character
  160. int strlenc(s,c)
  161. const char *s;
  162. char    c;
  163. {
  164.     const char *b = s;
  165.  
  166.     while (*s != c)
  167.     ++s;
  168.  
  169.     return(s - b);
  170. }
  171.  
  172. //      Given start and current, count newlines to come up with a line number
  173. //              !!! TODO: Add cache
  174. int ErrorLine(char *start, char *current)
  175. {
  176. int     linenum =1;
  177.  
  178.         for(;start < current; start++)
  179.                 if ( *start==LF )
  180.                         linenum++;
  181.  
  182.         return(linenum);
  183. }
  184.  
  185. // Do in-place removal of CR
  186. FilterCR(register char *leading)
  187. {
  188. register char *trailing=leading;
  189. register char c;
  190.  
  191.         while( c=*leading++ )
  192.                 {
  193.                 if (c != CR)
  194.                         *trailing++=c;
  195.                 }
  196.         *trailing=0;
  197.         trailing++;
  198.         *trailing=0;
  199.         trailing++;
  200.         *trailing=0;
  201.         trailing++;
  202.         *trailing=0;
  203.         trailing++;
  204. }
  205.  
  206. /*******************************************************************************
  207. **      @ Functions
  208. */
  209.  
  210. char *MAJOR_HEADING()           // Set filename for result file
  211. {
  212. int     len;
  213. char    *temp;
  214. char    c;
  215.  
  216.         len=CollectParagraph();
  217.  
  218.         if (temp=strchr(formatbuf,',')) // Use only first item of a multiple
  219.                 *temp=0;                // function example
  220.  
  221.         len = strlen( formatbuf );      // Recalculate length
  222.  
  223.         if (len < LINE_WIDTH-10 ) {
  224.                 strcpy(filename, pathname);
  225.  
  226.                 if( strlen(pathname) ) {
  227.                         c=pathname[strlen(pathname)-1];
  228.                         if (!( c==':' || c=='/' ))
  229.                                 strcat(filename, "/");
  230.                 }
  231.                 strcat(filename, formatbuf);
  232.                 strcpy(filename_nopath, formatbuf);
  233.                 strcat(filename, ".c");
  234.                 strcat(filename_nopath, ".c");
  235.         }
  236.         else    {
  237.                 strcpy(filename, pathname);
  238.                 strcat(filename, "/");
  239.                 strcat(filename, "** INVALID **");
  240.         }
  241. }
  242.  
  243. char *EXAMPLE()
  244. {
  245.         if( examplename )
  246.                 if( strcmp( examplename, filename_nopath ) ) {
  247.                         CollectParagraph();
  248.                         return(0);
  249.                         }
  250.  
  251.         unless( outfile=fopen(filename,"w" ) ) {
  252.             printf("Error: Can't write to \"%s\"\n",filename);
  253.             return(0);
  254.         }
  255.         printf("Processing file \"%s\"\n",filename);
  256.  
  257.         FormatParagraph(CollectParagraph(),"");
  258.  
  259.         fclose(outfile);
  260.         outfile=0;
  261. }
  262.  
  263. int CollectParagraph()
  264. {
  265. int     i=0;
  266.  
  267.     while( *inp )
  268.         {
  269.         if ( (*inp==LF) && (*(inp+1)==LF) )     // Two LF's signal end of para
  270.                 break;
  271.  
  272.         if ( *inp==CR ) {
  273.             printf("Error: File must not contain CR's\n");
  274.             break;
  275.             }
  276.  
  277.         if ( i > (MAX_PARAGRAPH-100) ) {
  278.             printf("Error: Paragraph too large!\n");
  279.             break;
  280.             }
  281.  
  282.         //      Escape double <<brackets>>. Skip single <brackets>
  283.         //
  284.         if ( inp[0] == '<' && !(inp[1] == '<') ) {
  285.                 if ( inp[1]=='R' && inp[2]=='>' )
  286.                         {
  287.                         formatbuf[i++]=LF;
  288.                         if ( inp[3] == '\n' )
  289.                                 inp++;
  290.                         inp += 3;
  291.                         }
  292.                 else    {
  293.                         while( *inp && !(*inp=='>') )
  294.                                 inp++;
  295.                         if (*inp)
  296.                                 inp++;  // Skip trailing >
  297.                         }
  298.                 }
  299.         else if ( inp[0] == '<' && inp[1] == '<' )
  300.                 formatbuf[i++]='<',inp += 2;
  301.         else if ( inp[0] == '>' && inp[1] == '>' )
  302.                 formatbuf[i++]='>',inp += 2;
  303.         else if ( *inp == LF )
  304.                 formatbuf[i++]=' ',inp++;
  305.         else
  306.                 formatbuf[i++]=*inp,inp++;
  307.         }
  308.     formatbuf[i]=0;
  309.     formatbuf[i+1]=0;
  310.     formatbuf[i+2]=0;
  311.     formatbuf[i+3]=0;
  312.  
  313.     return(i);
  314. }
  315.  
  316. void FormatParagraph(int slen,char *prestring)
  317. {
  318. int     pos=0;
  319. int     scan=0;
  320. int     perline= LINE_WIDTH + 1 - strlen(prestring) - indent;
  321. int     i;
  322.  
  323.     D1(printf("FormatParagraph. Slen=%d, prestring=%s\n", slen, prestring));
  324.     D2(printf("%s", formatbuf));
  325.  
  326.     // Process normal text paragraph.  Wrap words, nuke spaces at start
  327.     // of line, etc.  Handle <R>, grumble.
  328.     while ( pos < slen )
  329.         {
  330.  
  331.         // If there is a newline within the current line range, pump out
  332.         // that string.  Else set scan to just past end of line (or EOF)
  333.         // and work backwards to word-wrap.
  334.         scan=0;
  335.         for (i=0; i < perline; i++)
  336.                 {
  337.                 if ( !formatbuf[pos+i] )
  338.                         break;
  339.                 if ( formatbuf[pos+i] == '\n' )
  340.                         {
  341.                         scan = pos+i+1; // Include linefeed
  342.                         D(printf("Newline found at %d\n",i));
  343.                         break;
  344.                         }
  345.                 }
  346.  
  347.         if( !scan )
  348.                 {
  349.                 // Skip leading spaces
  350.                 while ( formatbuf[pos]==' ' )
  351.                         pos++;
  352.                 if ( pos >= slen )
  353.                         break;
  354.  
  355.                 scan = pos + perline;   // Just past end of line
  356.  
  357.                 if ( scan > slen)
  358.                         scan = slen;    // Set to EOF
  359.  
  360.                 // Scan backwards for NULL, LF, space separator or start of line
  361.                 while( scan > pos && formatbuf[scan] && formatbuf[scan] != ' ' )
  362.                         scan--;
  363.  
  364.                 D(printf("Word-wrapped to %d bytes\n",scan-pos));
  365.  
  366.                 if (pos == scan)
  367.                         printf("ERROR: Huge word (near line %d)\n",ErrorLine(startinp,inp));
  368.                 }
  369.  
  370.         if ( indenttextvalid )
  371.                 fwrite(indenttext,indent,1,outfile) , indenttextvalid=0;
  372.         else
  373.                 fwrite(allspaces,indent,1,outfile);
  374.  
  375.         fprintf(outfile,prestring);
  376.         fwrite(&formatbuf[pos],scan-pos,1,outfile);
  377.         if ( formatbuf[scan-1] != '\n' )
  378.                 fprintf(outfile,"\n");
  379.  
  380.         pos = scan;
  381.         }
  382.     fprintf(outfile,"\n");
  383. }
  384.  
  385.  
  386. /*******************************************************************************
  387. **      @ Function tables & flags
  388. */
  389. #define ATSKIP          4       // Longs per atstuff entry
  390.  
  391. #define AF_OPT          0x0001  // Option indenting
  392. #define AF_BODY         0x0002  // Body indenting
  393. #define AF_NOFLUSH      0x0004  // Disable flush before next @COMMAND
  394.  
  395. char *(*atstuff[])()={
  396. "@MAJOR HEADING",       MAJOR_HEADING,  AF_BODY,        0,
  397. "@EXAMPLE",             EXAMPLE,        AF_OPT,         0,
  398. "@WIDEEXAMPLE",         EXAMPLE,        AF_OPT,         0,
  399. "@EXAMPLE_LIB",         EXAMPLE,        AF_OPT,         0,
  400. 0,                      0,              0,              0,
  401. };
  402.  
  403. /*******************************************************************************
  404. **      Processfile.  Until reaching a null, scan the input file for
  405. **      @XXX keywords.  Executue @ function, or print warning and keep
  406. **      scanning.
  407. */
  408. void ProcessFile()
  409. {
  410. int     j;
  411. int     atindex;
  412.  
  413.     D(printf("ProccessFile: outfile=%lx, inp=%lx\n",outfile,inp));
  414.  
  415.     while( *inp )
  416.         {
  417.         if (*inp == LF)
  418.             *inp++;
  419.         else if (*inp == CR)
  420.             {
  421.             printf("Error: File must not contain CR's\n");
  422.             break;
  423.             }
  424.         else if (*inp == '@')
  425.             {
  426.             /*
  427.             **  Find matching @ command
  428.             */
  429.             for( atindex=0; atstuff[atindex]; atindex += ATSKIP)
  430.                 {
  431.                 if( !strncmp(atstuff[atindex], inp, strlen(atstuff[atindex])) )
  432.                     break;
  433.                 }
  434.  
  435.             /*
  436.             **  Execute @ command, if any.  Else flush any pending line.
  437.             */
  438.             if( !atstuff[atindex] )
  439.                 {
  440.                 // Skip to next signifcant thing
  441.                 inp++;
  442.                 while( *inp && !(*inp=='@') && !(inp[0]==LF && inp[1]==LF) )
  443.                     inp++;
  444.                 }
  445.             else{
  446.                 D1( printf("Matched tag: %s\n",atstuff[atindex]) );
  447.  
  448.                 while( *inp && !(*inp=='=') )   // Skip to '='
  449.                     inp++;
  450.                 unless( inp[1]==' ' && inp[2])
  451.                         {
  452.                         printf("Warning: badly formatted @ tag or no example (%d)\n",ErrorLine(startinp,inp));
  453.                         while( *inp && !(*inp=='@') && !(inp[0]==LF && inp[1]==LF) )
  454.                                inp++;
  455.                         }
  456.                 else    {
  457.                         inp += 2;
  458.  
  459.                         for( j=0; j<LINE_WIDTH+2; j++)
  460.                             outbuf[j]=' ';
  461.                         outbuf[j+1]=0;
  462.  
  463.  
  464.                         //      if( atstuff[atindex+3] )
  465.                         //          indent = atstuff[atindex+3];
  466.  
  467.                         if( indenttextvalid )
  468.                             printf("Warning: Left margin text lost (%d)\n",ErrorLine(startinp,inp));
  469.  
  470.                         (*atstuff[atindex+1])(inp);
  471.                         }
  472.                 }
  473.             }
  474.         else{
  475.             FormatParagraph(CollectParagraph(),"");
  476.             }
  477.         }
  478.     D(printf("End ProccessFile: outfile=%lx, inp=%lx\n",outfile,inp));
  479. }
  480.  
  481.